home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Misc / SciCalc1.1 / Source / OperatorStack.m < prev    next >
Text File  |  1994-04-24  |  10KB  |  336 lines

  1. /***(OperatorStack.m)**********************************************************
  2. *H* Push down stack for numeric operators                     V0.0, 09-FEB-91 *
  3. *C* V0.0 09-FEB-91 Initial version                                      --MDM *
  4. ******************************************************************************/
  5.  
  6. /* Standard C Library includes */
  7. #import <stdio.h>           /* Standard I/O functions and definitions */
  8. #import <stdlib.h>          /* Standard C memory allocation prototypes */
  9.  
  10. #import "OperatorStack.h"        /* OperatorStack interface specification */
  11.  
  12.  
  13. /* Class Private Data */
  14. typedef struct OSoperator
  15.     {
  16.     char *name;
  17.     int      precedence;
  18.     int   n_operands;
  19.     } OToperator;
  20.  
  21. /* Table describing each operator */
  22. static OToperator OVopTable[OPCODE_OpCodes] =
  23.     {
  24.         { "Equals",        4, 1 },
  25.         { "Plus",       14, 2 },
  26.         { "Minus",      14, 2 },
  27.         { "Multiply",     15, 2 },
  28.         { "Divide",     15, 2 },
  29.         { "OpenParen",     5, 0 },
  30.         { "CloseParen",  6, 0 },
  31.         { "SIN",        17, 1 },
  32.         { "ASIN",       17, 1 },
  33.         { "SINH",       17, 1 },
  34.         { "ASINH",      17, 1 },
  35.         { "COS",        17, 1 },
  36.         { "ACOS",       17, 1 },
  37.         { "COSH",       17, 1 },
  38.         { "ACOSH",      17, 1 },
  39.         { "TAN",        17, 1 },
  40.         { "ATAN",       17, 1 },
  41.         { "TANH",       17, 1 },
  42.         { "ATANH",      17, 1 },
  43.         { "EXP",        17, 1 },
  44.         { "LN",            17, 1 },
  45.         { "LOG",        17, 1 },
  46.         { "10^X",       17, 1 },
  47.         { "X^Y",        16, 2 },
  48.         { "XrootY",     16, 2 },
  49.         { "XSquared",    17, 1 },
  50.         { "SqrRoot",    17, 1 },
  51.         { "1overX",     17, 1 },
  52.         { "Factorial",  17, 1 },
  53.         { "Pi",         17, 1 },
  54.         { "Modify",     15, 2 },
  55.         { "Integer",    17, 1 },
  56.         { "And",        10, 2 },
  57.         { "Or",          8, 2 },
  58.         { "Not",        17, 1 },
  59.         { "Xor",         9, 2 },
  60.         { "LShift",     17, 1 },
  61.         { "RShift",     17, 1 }
  62.     };
  63.  
  64.  
  65.  
  66. @implementation OperatorStack
  67.  
  68.  
  69. /* Private Object Wide Definitions */
  70. #define OCnullStack     (OToperStackItem *) 0
  71.  
  72.  
  73.  
  74. /******************************************************************************
  75. * INSTANCE METHOD:- init                                                      *
  76. *   Initialize a new instance of a OperatorStack class.                      *
  77. ******************************************************************************/
  78. - init
  79.  
  80. {/* BEGIN:-init */
  81. self = [super init];
  82. OVstackTop  = OCnullStack;
  83. OVstackSize = 0;
  84. return self;
  85. }/* END:-init */
  86.  
  87.  
  88.  
  89. /******************************************************************************
  90. * INSTANCE METHOD:- free                                                   *
  91. *   All data currently on the OperatorStack is poped and freed, returning the *
  92. * allocated memory back to the system pool.                                   *
  93. ******************************************************************************/
  94. - free
  95.  
  96. {   /* Local Variables */
  97.     OToperStackItem *tmp_blink;
  98.  
  99. /* BEGIN free */
  100. while (OVstackTop != OCnullStack)
  101.     {/* Get pointer to lower stack item and free top item */
  102.     tmp_blink = OVstackTop->blink;
  103.     free( (char *) OVstackTop );
  104.     OVstackTop  = tmp_blink;
  105.     OVstackSize = 0;
  106.     }
  107.  
  108. /* Request super class to perform its free method */
  109. return [super free];
  110. }/* END free */
  111.  
  112.  
  113.  
  114. /******************************************************************************
  115. * INSTANCE METHOD:- ClearStack                                                   *
  116. *   Pop and free each element on the stack until the stack is empty.          *
  117. ******************************************************************************/
  118. - ClearStack
  119.  
  120. {   /* Local Variables */
  121.     OToperStackItem  *tmp_blink;
  122.  
  123. /* BEGIN Clear */
  124. while ( OVstackTop )
  125.     {/* Stack is not empty, free top item */
  126.     tmp_blink  = OVstackTop->blink;
  127.     free ( (char *) OVstackTop );
  128.     OVstackTop = tmp_blink;
  129.     }
  130.  
  131. OVstackSize = 0;
  132. return self;
  133. }/* END ClearStack */
  134.  
  135.  
  136.  
  137. /******************************************************************************
  138. * INSTANCE METHOD:- ComparePrecedence                                         *
  139. *   Compares the  precedence  of  opcode against the opcode on the top of the *
  140. * stack and returns the difference in the result argument.  The comparison is *
  141. * made by subtracting the  numerical  precedence value of the supplied opcode *
  142. * with that of the opcode on the top of the stack.  If the stack is empty the *
  143. * supplied  opcode  is  compared  against  a  precedence  value of zero.  The *
  144. * returned value has the following meanings:                                *
  145. *       result >= 1: opcode has higher precedence stack top opcode.              *
  146. *       result == 0: opcode and stack top opcode are of equal precedence.     *
  147. *       result <= 1: opcode is of lesser precedence than stack top opcode.    *
  148. ******************************************************************************/
  149. - ComparePrecedence: (int) opcode: (int *) result
  150.  
  151. {/* BEGIN ComparePrecedence */
  152. if (opcode < 0 || opcode > OPCODE_LastOpCode)
  153.     return nil;    /* return failure status */
  154.  
  155. if ( OVstackSize > 0 )
  156.     /* Stack is not empty, use precedence of opcode on stack top */
  157.     *result = OVopTable[opcode].precedence - OVopTable[OVstackTop->opcode].precedence;
  158. else
  159.     /* Stack is empty, assume a precedence value of zero */
  160.     *result = OVopTable[opcode].precedence - 0;
  161.  
  162. return self;
  163. }/* END ComparePrecedence */
  164.  
  165.  
  166.  
  167. /******************************************************************************
  168. * INSTANCE METHOD:- GetSize                                                      *
  169. *   Return the current number of items in the Value Stack.                    *
  170. ******************************************************************************/
  171. - (unsigned long) GetSize
  172.  
  173. {/* BEGIN GetSize */
  174. return OVstackSize;
  175. }/* END GetSize */
  176.  
  177.  
  178.  
  179. /******************************************************************************
  180. * INSTANCE METHOD:- NumberOfOperands                                             *
  181. *   Return the operands that the given opcode requires.                          *
  182. ******************************************************************************/
  183. - NumberOfOperands :(int)opcode :(int*)noperands
  184.  
  185. {/* BEGIN NumberOfOperands */
  186. if ( opcode >= OPCODE_Equals && opcode <= OPCODE_LastOpCode )
  187.     {/* The caller supplied a legal opcode, return successfully */
  188.     *noperands = OVopTable[opcode].n_operands;
  189.     return self;
  190.     }
  191.  
  192. else
  193.     /* The caller supplied an invalid opcode, return with error status */
  194.     return nil;
  195. }/* END NumberOfOperands */
  196.  
  197.  
  198.  
  199. /******************************************************************************
  200. * INSTANCE METHOD:- Peek                                                      *
  201. *   Return the value on the top  of  the  stack  without removing it from the *
  202. * stack.                                                                      *
  203. ******************************************************************************/
  204. - Peek: (int *) opcode
  205.  
  206. {/* BEGIN Peek */
  207. if ( OVstackTop )
  208.     {/* The stack is not emptry */
  209.     *opcode = OVstackTop->opcode;
  210.     return self;    /* succesful status */
  211.     }
  212. else
  213.     {/* Report illegal reference to standard error */
  214. #ifdef DEBUG
  215.     fprintf(stderr, "OperatorStack: Peek on empty stack returning -1\n");
  216. #endif
  217.     *opcode = -1;
  218.     return nil;    /* failure status */
  219.     }
  220. }/* END Peek */
  221.  
  222.  
  223.  
  224. /******************************************************************************
  225. * INSTANCE METHOD:- Pop                                                        *
  226. *   Return the value opcode on the top of the stack and free top stack item.  *
  227. ******************************************************************************/
  228. - Pop: (int *) opcode
  229.  
  230. {   /* Local Variables */
  231.     OToperStackItem  *tmp_blink;
  232.  
  233. /* BEGIN Pop */
  234. if ( OVstackTop )
  235.     {/* Stack is not empty, free top item and return top value */
  236.     *opcode = OVstackTop->opcode;
  237.     tmp_blink  = OVstackTop->blink;
  238.     free ( (char *) OVstackTop );
  239.     OVstackTop = tmp_blink;
  240.     OVstackSize--;
  241.     return self;
  242.     }
  243.  
  244. else
  245.     {/* Stack is empty report error, return -1 */
  246. #ifdef DEBUG
  247.     fprintf(stderr, "OperatorStack: Pop on empty stack returning -1\n");
  248. #endif
  249.     *opcode = -1;
  250.     return nil;        /* failure status */
  251.     }
  252. }/* END Pop */
  253.  
  254.  
  255.  
  256. /******************************************************************************
  257. * INSTANCE METHOD:- Push                                                        *
  258. *   Push an opcode value on the stack.   We allocate a new stack item setting *
  259. * its opcode field to the supplied opcode value, and its blink field to point *
  260. * to the current stack top.  If a new stack item cannot be allocated an error *
  261. * message is written to stderr.                                                  *
  262. ******************************************************************************/
  263. - Push: (int) opcode
  264.  
  265. {   /* Local Variables */
  266.     OToperStackItem  *new_item;
  267.  
  268. /* BEGIN Push */
  269. /* Allocate a new stack item */
  270. new_item = (OToperStackItem *) malloc(sizeof(OToperStackItem));
  271.  
  272. if ( new_item )
  273.     {/* New stack item allocated, initialize and link in new stack top */
  274.     new_item->opcode = opcode;
  275.     new_item->blink = OVstackTop;
  276.     OVstackTop = new_item;
  277.     OVstackSize++;
  278.     return self;    
  279.     }
  280.  
  281. else
  282.     {/* Allocation failed, report error to stderr */
  283. #ifdef DEBUG
  284.     fprintf(stderr, "OperatorStack: Push allocation failure\n");
  285. #endif
  286.     return nil;
  287.     }
  288. }/* END Push */
  289.  
  290.  
  291.  
  292. /******************************************************************************
  293. * INSTANCE METHOD:- PrintStack                                                *
  294. *   Print out the contents of the stack to standard output.                   *
  295. ******************************************************************************/
  296. - PrintStack
  297.  
  298. {   /* Local Variables */
  299.     OToperStackItem  *trace_link;
  300.     int                  oti;          /* operator table index */
  301.     long            level;
  302.  
  303. /* BEGIN PrintStack */
  304. if ( OVstackTop )
  305.     {/* The stack is not empty so dump its contents */
  306.     trace_link = OVstackTop;
  307.     level      = 0;
  308.  
  309.     while ( trace_link )
  310.         {/* Not at bottom, print this item */
  311.         oti = trace_link->opcode;
  312. #ifdef DEBUG
  313.         printf("%s\t%d\t%d\t:(%ld)\n",
  314.                OVopTable[oti].name,
  315.                OVopTable[oti].precedence,
  316.                OVopTable[oti].n_operands,
  317.                level--);
  318. #endif
  319.         trace_link = trace_link->blink;
  320.         }
  321.     }
  322.  
  323. else
  324.     {/* Stack is empty so print a message */
  325. #ifdef DEBUG
  326.     printf("OperatorStack: stack empty\n");
  327. #endif
  328.     }
  329.  
  330. return self;
  331. }/* END PrintStack */
  332.  
  333.  
  334.  
  335. @end /* ValueStack Implementation */
  336.